/* $Id$ */
package net.sourceforge.ftgl.demos.showroom;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;

import net.java.games.jogl.Animator;
import net.java.games.jogl.GLCanvas;
import net.java.games.jogl.GLCapabilities;
import net.java.games.jogl.GLDrawableFactory;
import net.java.games.jogl.impl.NativeLibLoader;
import net.sourceforge.ftgl.demos.showroom.scene.RenderAction;
import net.sourceforge.ftgl.demos.showroom.scene.Scene;
import net.sourceforge.ftgl.demos.showroom.scene.SetAWTFontAction;
import net.sourceforge.ftgl.util.loader.LibraryLoader;

/**
 * @author funsheep
 *
 */
public class FTGLDemo implements KeyListener, ActionListener, MouseWheelListener
{

	private final Scene scene;
	private final FTJOGLRenderer renderer;
	
	
	public FTGLDemo(GLCanvas drawable)
	{
		final String [] allAWTFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
		this.scene  = new Scene(allAWTFonts[0]);
		this.renderer = new FTJOGLRenderer(this.scene);

		final JFrame frame = new JFrame("FTGL TEST");
		frame.setBounds(50,50, 640, 480);

		JComboBox box = new JComboBox(allAWTFonts);

		drawable.setSize(640, 480);
		frame.getContentPane().setLayout(new BorderLayout());
		frame.getContentPane().add(drawable, BorderLayout.CENTER);
		frame.getContentPane().add(box, BorderLayout.SOUTH);
		frame.pack();
		
		box.addActionListener(this);
		drawable.addMouseMotionListener(this.scene.tb);
		drawable.addMouseWheelListener(this);
		drawable.addMouseListener(this.scene.tb);
		drawable.addKeyListener(this);
		drawable.addGLEventListener(this.renderer);

		drawable.requestFocus();

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
	
	/**
	 * {@inheritDoc}
	 */
	public void actionPerformed(ActionEvent e)
	{
		if (e.getSource() instanceof JComboBox)
		{
			JComboBox b = (JComboBox) e.getSource();
			String selfont = b.getSelectedItem().toString();
			this.renderer.add(new SetAWTFontAction(this.scene, selfont));
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void keyTyped(final KeyEvent e)
	{
		this.renderer.add(new RenderAction(){

			public void run(long millis)
			{
				char keyChar = e.getKeyChar();
				if (keyChar!=KeyEvent.CHAR_UNDEFINED && keyChar!=KeyEvent.VK_BACK_SPACE)
				{
					if (scene.mode == Scene.INTERACTIVE)
					{
						scene.displayString = String.valueOf(keyChar);
					}
					else
					{
						scene.displayString = scene.displayString.substring(0,scene.carat)+keyChar+scene.displayString.substring(scene.carat);
						scene.carat++;
					}
				}
			}
			
		});
	}

	/**
	 * {@inheritDoc}
	 * <p>Note: added to allow zooming
	 */
	public void mouseWheelMoved(final MouseWheelEvent e)
	{
		this.renderer.add(new RenderAction(){

			public void run(long millis)
			{
				if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK)==0)
				{
					float amount = -e.getWheelRotation();
					if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK)>0)
						amount /= 10;
					scene.zoom += amount;
					if (scene.zoom<=0)
						scene.zoom = 1f;
					return;
				}
				else if ((e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK)>0)
				{
//					FTGLExtrdFont f = (FTGLExtrdFont)this.fonts[FTGL_EXTRUDE];
//
//					float amount = -e.getWheelRotation();
//					if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK)>0)
//						amount *= 10;
//					f.setDepth(f.getDepth() + amount);
//					return;
				}
			}
			
		});
	}


	/**
	 * Processes the keys delivered by the KeyListener,
	 */
	public void processKey(final KeyEvent e)
	{
		this.renderer.add(new RenderAction(){

			public void run(long millis)
			{
				switch (e.getKeyCode())
				{
					case KeyEvent.VK_ESCAPE:
						renderer.running = true;
						break;
					case KeyEvent.VK_BACK_SPACE:
						if (scene.carat>0)
						{
							StringBuffer sb = new StringBuffer(scene.displayString);
							sb.deleteCharAt(scene.carat-1);
							scene.displayString = sb.toString();
							scene.carat = scene.carat-1;
						}
						break;
					case KeyEvent.VK_ENTER:
						if (scene.mode == Scene.EDITING)
						{
							scene.mode = Scene.INTERACTIVE;
							scene.carat = -1;
							if (scene.displayString!=null && scene.displayString.length()>0)
								scene.displayString = scene.displayString.substring(0,1);
							else
								scene.displayString = "a";
						}
						else
						{
							scene.carat = Math.max(scene.displayString.length()-1,0);
							scene.mode = Scene.EDITING;
						}
						break;
					case KeyEvent.VK_LEFT:
						scene.carat = Math.max(scene.carat-1,0);
						break;
					case KeyEvent.VK_RIGHT:
						scene.carat = Math.min(scene.carat+1,scene.displayString.length());
						break;
					case KeyEvent.VK_PAGE_UP:
						scene.setCurrentFTFont(++scene.current_ftfont);
						break;
					case KeyEvent.VK_PAGE_DOWN:
						scene.setCurrentFTFont(--scene.current_ftfont);
						break;
					case KeyEvent.VK_PLUS:
						scene.setCurrentColor(++scene.current_color);
						break;
					case KeyEvent.VK_MINUS:
						scene.setCurrentColor(--scene.current_color);
						break;
					case KeyEvent.VK_F1:
						scene.displayString = "jftgl";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F2:
						scene.displayString = "Thou shall not steal.";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F3:
						scene.displayString = "My birthday present from me for me.";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F4:
						scene.displayString = "Sorry, I wrecked your car.";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F5:
						scene.displayString = "Happy wife, happy life.";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F6:
						scene.displayString = "Call your mom, she worries.";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F7:
						scene.displayString = "Ding Ding Bling Bling.";
						scene.carat = scene.displayString.length();
						break;
					case KeyEvent.VK_F8:
						scene.displayString = "\u6FB3\u9580";
						scene.carat = scene.displayString.length();
						break;
					default:
	//					if (this.key.getKeyChar()==KeyEvent.CHAR_UNDEFINED)
	//						System.err.println("Ignored:"+this.key);
						break;
				}
				e.consume();
			}
			
		});
	}

	public void keyPressed(KeyEvent e)
	{
		//nothing to do
	}


	public void keyReleased(KeyEvent e)
	{
		this.processKey(e);
	}


	public static void main(String[] args)
	{
		Frame.getFrames();
		NativeLibLoader.disableLoading();
		new LibraryLoader().load("jogl");
		// glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
		// glutInitWindowPosition(50, 50);
		// glutInitWindowSize( w_win, h_win);

		GLCapabilities glc = new GLCapabilities();
		glc.setSampleBuffers(true);
		glc.setDoubleBuffered(true);
		GLDrawableFactory glf = GLDrawableFactory.getFactory();
		GLCanvas drawable = glf.createGLCanvas(glc);

		System.out.println("DRAWABLE GL IS: " + drawable.getGL().getClass().getName());
		System.out.println("DRAWABLE GLU IS: " + drawable.getGLU().getClass().getName());

		final Animator animator = new Animator(drawable);
		//final Thread t = Thread.currentThread();
		FTGLDemo demo = new FTGLDemo(drawable);


		animator.start();
		System.out.println(demo.renderer.toString());
		try
		{
			int count_alt = 0;
			long time_alt = System.currentTimeMillis();
			while (!Thread.interrupted() && !demo.renderer.running)
			{
				Thread.sleep(5000);

				long time = System.currentTimeMillis();
				int count = FTJOGLRenderer.framesCounted;

				long dt = time - time_alt;
				int dc = count - count_alt;
				count_alt = count;
				System.out.println("" + dc + " frames in " + dt / 1000f + " seconds = "
					+ (1000f * dc / dt) + " FPS at " + drawable.getWidth() + "x"+ drawable.getHeight());

				time_alt = time;
			}
		}
		catch (InterruptedException e)
		{
			System.out.println("Thread was interrupted.");
		}
		animator.stop();
		drawable.setEnabled(false);
	}


}
